package com.cenxi.config;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@Configuration
public class RedisCacheConfig {

	@Bean
	@Primary
	public RedisCacheManager redisCache(RedisConnectionFactory connectionFactory) {
		RedisCacheConfiguration config = instanceConfig(1800L);
		return RedisCacheManager.builder(connectionFactory)
				.cacheDefaults(config)
				.transactionAware()
				.build();
	}

	private RedisCacheConfiguration instanceConfig(Long ttl) {

		Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
		ObjectMapper objectMapper = new ObjectMapper();
		objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
		objectMapper.registerModule(new JavaTimeModule());
		// 去掉各种@JsonSerialize注解的解析
		objectMapper.configure(MapperFeature.USE_ANNOTATIONS, false);
		// 只针对非空的值进行序列化
		objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
		// 将类型序列化到属性json字符串中
		objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

		jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
		return RedisCacheConfiguration.defaultCacheConfig()
				.disableCachingNullValues()
				// 设置缓存时间
				.entryTtl(Duration.ofDays(ttl))
				.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));

	}

	/**
	 * 重写redis序列化方法
	 */
	@Bean
	public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
		RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
		redisTemplate.setConnectionFactory(factory);
		// 创建json序列化对象
		GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
		// key序列化stringjson
		redisTemplate.setKeySerializer(new StringRedisSerializer());
		// value序列化json
		redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
		// 设置hash序列化string
		redisTemplate.setHashKeySerializer(new StringRedisSerializer());
		// hash key序列化string
		redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
		// 初始化redis完成序列化方法
		redisTemplate.afterPropertiesSet();
		return redisTemplate;
	}

}
